๊ฒฌ๊ณ ํ๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์ฝ๋๋ฅผ ์ํด ํ์ ์์ ์ฑ์ ํ์ฉํ ๊ณ ๊ธ TypeScript ํ ์คํ ์ ๋ต์ ํ๊ตฌํฉ๋๋ค. ์ ๋ขฐํ ์ ์๋ ํ ์คํธ๋ฅผ ์์ฑํ๊ธฐ ์ํด ํ์ ์ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ฐ์ธ์.
TypeScript ํ ์คํ : ๊ฒฌ๊ณ ํ ์ฝ๋๋ฅผ ์ํ ํ์ ์์ ์ฑ ํ ์คํธ ๊ตฌํ ์ ๋ต
์ํํธ์จ์ด ๊ฐ๋ฐ ์์ญ์์ ์ฝ๋ ํ์ง ๋ณด์ฅ์ ๊ฐ์ฅ ์ค์ํฉ๋๋ค. TypeScript๋ ๊ฐ๋ ฅํ ํ์ดํ ์์คํ ์ ํตํด ๋ ์ ๋ขฐํ ์ ์๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์๋ ๋ ํนํ ๊ธฐํ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด ๊ธ์ ๊ฒฌ๊ณ ํ๊ณ ํจ๊ณผ์ ์ธ ํ ์คํธ๋ฅผ ์์ฑํ๊ธฐ ์ํด ํ์ ์์ ์ฑ์ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ค์ ์ ๋์ด ๋ค์ํ TypeScript ํ ์คํ ์ ๋ต์ ์ฌ์ธต์ ์ผ๋ก ๋ค๋ฃน๋๋ค. ์ฐ๋ฆฌ๋ TypeScript ํ ์คํ ์ ๋ํ ํฌ๊ด์ ์ธ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํ๋ฉฐ, ๋ค์ํ ํ ์คํธ ์ ๊ทผ ๋ฐฉ์, ํ๋ ์์ํฌ ๋ฐ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ํ๊ตฌํ ๊ฒ์ ๋๋ค.
ํ ์คํ ์์ ํ์ ์์ ์ฑ์ด ์ค์ํ ์ด์
TypeScript์ ์ ์ ํ์ดํ ์์คํ ์ ํ ์คํ ์์ ์ฌ๋ฌ ๊ฐ์ง ์ด์ ์ ์ ๊ณตํฉ๋๋ค:
- ์กฐ๊ธฐ ์ค๋ฅ ๊ฐ์ง: TypeScript๋ ๊ฐ๋ฐ ์ค์ ํ์ ๊ด๋ จ ์ค๋ฅ๋ฅผ ๊ฐ์งํ์ฌ ๋ฐํ์ ์คํจ ๊ฐ๋ฅ์ฑ์ ์ค์ผ ์ ์์ต๋๋ค.
- ํฅ์๋ ์ฝ๋ ์ ์ง๋ณด์์ฑ: ํ์ ์ ์ฝ๋๋ฅผ ์ดํดํ๊ณ ๋ฆฌํฉํ ๋งํ๊ธฐ ์ฝ๊ฒ ๋ง๋ค์ด ๋ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ํ ์คํธ๋ก ์ด์ด์ง๋๋ค.
- ํฅ์๋ ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง: ํ์ ์ ๋ณด๋ ๋ ํฌ๊ด์ ์ด๊ณ ๋ชฉํ ์งํฅ์ ์ธ ํ ์คํธ ์์ฑ์ ์๋ดํ ์ ์์ต๋๋ค.
- ๋๋ฒ๊น ์๊ฐ ๋จ์ถ: ํ์ ์ค๋ฅ๋ ๋ฐํ์ ์ค๋ฅ์ ๋นํด ์ง๋จํ๊ณ ์์ ํ๊ธฐ ๋ ์ฝ์ต๋๋ค.
ํ ์คํ ์์ค: ํฌ๊ด์ ์ธ ๊ฐ์
๊ฒฌ๊ณ ํ ํ ์คํ ์ ๋ต์ ํฌ๊ด์ ์ธ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด ์ฌ๋ฌ ์์ค์ ํ ์คํธ๋ฅผ ํฌํจํฉ๋๋ค. ์ด๋ฌํ ์์ค์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ๋จ์ ํ ์คํธ: ๊ฐ๋ณ ์ปดํฌ๋ํธ ๋๋ ํจ์๋ฅผ ๋ ๋ฆฝ์ ์ผ๋ก ํ ์คํธํฉ๋๋ค.
- ํตํฉ ํ ์คํธ: ๋ค๋ฅธ ๋จ์ ๋๋ ๋ชจ๋ ๊ฐ์ ์ํธ ์์ฉ์ ํ ์คํธํฉ๋๋ค.
- ์ข ๋จ ๊ฐ(E2E) ํ ์คํธ: ์ฌ์ฉ์ ๊ด์ ์์ ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ํฌํ๋ก์ฐ๋ฅผ ํ ์คํธํฉ๋๋ค.
TypeScript์ ๋จ์ ํ ์คํธ: ์ปดํฌ๋ํธ ์์ค ์ ๋ขฐ์ฑ ๋ณด์ฅ
๋จ์ ํ ์คํธ ํ๋ ์์ํฌ ์ ํ
TypeScript์์ ์ฌ์ฉํ ์ ์๋ ๋ช ๊ฐ์ง ์ธ๊ธฐ ์๋ ๋จ์ ํ ์คํธ ํ๋ ์์ํฌ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- Jest: ๋ชจํน, ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง, ์ค๋ ์ท ํ ์คํ ๊ณผ ๊ฐ์ ๋ด์ฅ ๊ธฐ๋ฅ์ ๊ฐ์ถ ํฌ๊ด์ ์ธ ํ ์คํ ํ๋ ์์ํฌ์ ๋๋ค. ์ฌ์ฉ ํธ์์ฑ๊ณผ ๋ฐ์ด๋ ์ฑ๋ฅ์ผ๋ก ์ ์๋ ค์ ธ ์์ต๋๋ค.
- Mocha: ๋จ์ธ(assertion) ๋ฐ ๋ชจํน(mocking)๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ํด ์ถ๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ํ ์ ์ฐํ๊ณ ํ์ฅ ๊ฐ๋ฅํ ํ ์คํ ํ๋ ์์ํฌ์ ๋๋ค.
- Jasmine: ๊น๋ํ๊ณ ์ฝ๊ธฐ ์ฌ์ด ๊ตฌ๋ฌธ์ ๊ฐ์ง ๋ ๋ค๋ฅธ ์ธ๊ธฐ ์๋ ํ ์คํ ํ๋ ์์ํฌ์ ๋๋ค.
์ด ๊ธ์์๋ Jest์ ๋จ์์ฑ๊ณผ ํฌ๊ด์ ์ธ ๊ธฐ๋ฅ์ ์ฃผ๋ก ์ฌ์ฉํ ๊ฒ์ ๋๋ค. ํ์ง๋ง ๋ ผ์๋ ์์น์ ๋ค๋ฅธ ํ๋ ์์ํฌ์๋ ์ ์ฉ๋ฉ๋๋ค.
์์: TypeScript ํจ์ ๋จ์ ํ ์คํธ
ํ ์ธ ๊ธ์ก์ ๊ณ์ฐํ๋ ๋ค์ TypeScript ํจ์๋ฅผ ๊ณ ๋ คํด ๋ณด์ธ์:
// src/discountCalculator.ts
export function calculateDiscount(price: number, discountPercentage: number): number {
if (price < 0 || discountPercentage < 0 || discountPercentage > 100) {
throw new Error("Invalid input: Price and discount percentage must be non-negative, and discount percentage must be between 0 and 100.");
}
return price * (discountPercentage / 100);
}
๋ค์์ Jest๋ฅผ ์ฌ์ฉํ์ฌ ์ด ํจ์์ ๋ํ ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๋๋ค:
// test/discountCalculator.test.ts
import { calculateDiscount } from '../src/discountCalculator';
describe('calculateDiscount', () => {
it('should calculate the discount amount correctly', () => {
expect(calculateDiscount(100, 10)).toBe(10);
expect(calculateDiscount(50, 20)).toBe(10);
expect(calculateDiscount(200, 5)).toBe(10);
});
it('should handle zero discount percentage correctly', () => {
expect(calculateDiscount(100, 0)).toBe(0);
});
it('should handle 100% discount correctly', () => {
expect(calculateDiscount(100, 100)).toBe(100);
});
it('should throw an error for invalid input (negative price)', () => {
expect(() => calculateDiscount(-100, 10)).toThrowError("Invalid input: Price and discount percentage must be non-negative, and discount percentage must be between 0 and 100.");
});
it('should throw an error for invalid input (negative discount percentage)', () => {
expect(() => calculateDiscount(100, -10)).toThrowError("Invalid input: Price and discount percentage must be non-negative, and discount percentage must be between 0 and 100.");
});
it('should throw an error for invalid input (discount percentage > 100)', () => {
expect(() => calculateDiscount(100, 110)).toThrowError("Invalid input: Price and discount percentage must be non-negative, and discount percentage must be between 0 and 100.");
});
});
์ด ์์๋ TypeScript์ ํ์ ์์คํ ์ด ์ฌ๋ฐ๋ฅธ ๋ฐ์ดํฐ ํ์ ์ด ํจ์์ ์ ๋ฌ๋๋๋ก ๋ณด์ฅํ๊ณ , ํ ์คํธ๊ฐ ์ฃ์ง ์ผ์ด์ค ๋ฐ ์ค๋ฅ ์กฐ๊ฑด์ ํฌํจํ ๋ค์ํ ์๋๋ฆฌ์ค๋ฅผ ์ปค๋ฒํ๋ ๋ฐ ์ด๋ป๊ฒ ๋์์ด ๋๋์ง ๋ณด์ฌ์ค๋๋ค.
๋จ์ ํ ์คํธ์์ TypeScript ํ์ ํ์ฉ
TypeScript์ ํ์ ์์คํ ์ ๋จ์ ํ ์คํธ์ ๋ช ํ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ํฅ์์ํค๋ ๋ฐ ์ฌ์ฉ๋ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ํจ์๊ฐ ๋ฐํํ๋ ๊ฐ์ฒด์ ์์ ๊ตฌ์กฐ๋ฅผ ์ ์ํ ์ ์์ต๋๋ค:
interface User {
id: number;
name: string;
email: string;
}
function getUser(id: number): User {
// ... implementation ...
return { id: id, name: "John Doe", email: "john.doe@example.com" };
}
it('should return a user object with the correct properties', () => {
const user = getUser(123);
expect(user.id).toBe(123);
expect(user.name).toBe('John Doe');
expect(user.email).toBe('john.doe@example.com');
});
User ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํจ์ผ๋ก์จ, ํ
์คํธ๊ฐ ์ฌ๋ฐ๋ฅธ ์์ฑ๊ณผ ํ์
์ ํ์ธํ๊ณ ์์์ ๋ณด์ฅํ์ฌ ๋ ๊ฒฌ๊ณ ํ๊ณ ์ค๋ฅ ๋ฐ์ ๊ฐ๋ฅ์ฑ์ด ๋ฎ์์ง๋๋ค.
TypeScript๋ฅผ ์ด์ฉํ ๋ชจํน ๋ฐ ์คํฐ๋น
๋จ์ ํ ์คํธ์์, ํ ์คํธ ๋์ ๋จ์๋ฅผ ์ข ์์ฑ์ ๋ชจํนํ๊ฑฐ๋ ์คํฐ๋นํ์ฌ ๊ฒฉ๋ฆฌํ๋ ๊ฒ์ด ์ข ์ข ํ์ํฉ๋๋ค. TypeScript์ ํ์ ์์คํ ์ ๋ชจ์(mock) ๋ฐ ์คํ (stub)์ด ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌํ๋๊ณ ์์ ์ธํฐํ์ด์ค๋ฅผ ์ค์ํ๋์ง ํ์ธํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
์ธ๋ถ ์๋น์ค์ ์์กดํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํ๋ ํจ์๋ฅผ ๊ณ ๋ คํด ๋ณด์ธ์:
interface DataService {
getData(id: number): Promise;
}
class MyComponent {
constructor(private dataService: DataService) {}
async fetchData(id: number): Promise {
return this.dataService.getData(id);
}
}
MyComponent๋ฅผ ํ
์คํธํ๊ธฐ ์ํด DataService์ ๋ชจ์ ๊ตฌํ์ ์์ฑํ ์ ์์ต๋๋ค:
class MockDataService implements DataService {
getData(id: number): Promise {
return Promise.resolve(`Data for id ${id}`);
}
}
it('should fetch data from the data service', async () => {
const mockDataService = new MockDataService();
const component = new MyComponent(mockDataService);
const data = await component.fetchData(123);
expect(data).toBe('Data for id 123');
});
DataService ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํจ์ผ๋ก์จ MockDataService๋ ํ์ํ ๋ฉ์๋๋ฅผ ์ฌ๋ฐ๋ฅธ ํ์
์ผ๋ก ์ ๊ณตํ์ฌ ํ
์คํ
์ค ํ์
๊ด๋ จ ์ค๋ฅ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
TypeScript์ ํตํฉ ํ ์คํธ: ๋ชจ๋ ๊ฐ ์ํธ ์์ฉ ๊ฒ์ฆ
ํตํฉ ํ ์คํธ๋ ์ ํ๋ฆฌ์ผ์ด์ ๋ด์ ์ฌ๋ฌ ๋จ์ ๋๋ ๋ชจ๋ ๊ฐ์ ์ํธ ์์ฉ์ ๊ฒ์ฆํ๋ ๋ฐ ์ค์ ์ ๋ก๋๋ค. ์ด ํ ์คํธ ์์ค์ ์์คํ ์ ์ฌ๋ฌ ๋ถ๋ถ์ด ์ฌ๋ฐ๋ฅด๊ฒ ํจ๊ป ์๋ํ๋์ง ํ์ธํ๋ ๋ฐ ์ค์ํฉ๋๋ค.
์์: ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฌ์ฉํ ํตํฉ ํ ์คํธ
๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ๊ฒ์ํ๊ธฐ ์ํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ ์์ฉํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ณ ๋ คํด ๋ณด์ธ์. ์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ํ ํตํฉ ํ ์คํธ๋ ๋ค์์ ํฌํจํ ์ ์์ต๋๋ค:
- ํ ์คํธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค์ .
- ํ ์คํธ ๋ฐ์ดํฐ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฑ์ฐ๊ธฐ.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ ์์ฉํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋ ์คํ.
- ๋ฐ์ดํฐ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ ์ฅ๋๊ณ ๊ฒ์๋๋์ง ํ์ธ.
- ํ ์คํธ ์๋ฃ ํ ํ ์คํธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๋ฆฌ.
// integration/userRepository.test.ts
import { UserRepository } from '../src/userRepository';
import { DatabaseConnection } from '../src/databaseConnection';
describe('UserRepository', () => {
let userRepository: UserRepository;
let databaseConnection: DatabaseConnection;
beforeAll(async () => {
databaseConnection = new DatabaseConnection('test_database'); // Use a separate test database
await databaseConnection.connect();
userRepository = new UserRepository(databaseConnection);
});
afterAll(async () => {
await databaseConnection.disconnect();
});
beforeEach(async () => {
// Clear the database before each test
await databaseConnection.clearDatabase();
});
it('should create a new user in the database', async () => {
const newUser = { id: 1, name: 'Alice', email: 'alice@example.com' };
await userRepository.createUser(newUser);
const retrievedUser = await userRepository.getUserById(1);
expect(retrievedUser).toEqual(newUser);
});
it('should retrieve a user from the database by ID', async () => {
const existingUser = { id: 2, name: 'Bob', email: 'bob@example.com' };
await userRepository.createUser(existingUser);
const retrievedUser = await userRepository.getUserById(2);
expect(retrievedUser).toEqual(existingUser);
});
});
์ด ์์๋ ํ
์คํธ ํ๊ฒฝ์ ์ค์ ํ๊ณ , ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ ์์ฉํ๋ฉฐ, ์ ํ๋ฆฌ์ผ์ด์
์ฝ๋๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ ์ฅํ๊ณ ๊ฒ์ํ๋์ง ํ์ธํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํฐํฐ(์: User)์ TypeScript ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ฉด ํตํฉ ํ
์คํธ ํ๋ก์ธ์ค ์ ๋ฐ์ ๊ฑธ์ณ ํ์
์์ ์ฑ์ด ๋ณด์ฅ๋ฉ๋๋ค.
ํตํฉ ํ ์คํธ์์ ์ธ๋ถ ์๋น์ค ๋ชจํน
ํตํฉ ํ ์คํธ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์กดํ๋ ์ธ๋ถ ์๋น์ค๋ฅผ ๋ชจ์ํ๋ ๊ฒ์ด ์ข ์ข ํ์ํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ค์ ์๋น์ค์ ์์กดํ์ง ์๊ณ ๋ ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ ์๋น์ค ๊ฐ์ ํตํฉ์ ํ ์คํธํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ์ ํ๋ฆฌ์ผ์ด์ ์ด ๊ฒฐ์ ๊ฒ์ดํธ์จ์ด์ ํตํฉ๋๋ ๊ฒฝ์ฐ, ๊ฒ์ดํธ์จ์ด์ ๋ชจ์ ๊ตฌํ์ ์์ฑํ์ฌ ๋ค์ํ ๊ฒฐ์ ์๋๋ฆฌ์ค๋ฅผ ์๋ฎฌ๋ ์ด์ ํ ์ ์์ต๋๋ค.
TypeScript์ ์ข ๋จ ๊ฐ(E2E) ํ ์คํธ: ์ฌ์ฉ์ ์ํฌํ๋ก์ฐ ์๋ฎฌ๋ ์ด์
์ข ๋จ ๊ฐ(E2E) ํ ์คํธ๋ ์ฌ์ฉ์ ๊ด์ ์์ ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ํฌํ๋ก์ฐ๋ฅผ ํ ์คํธํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค. ์ด ์ ํ์ ํ ์คํธ๋ ์ค์ ํ๊ฒฝ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋์ง ํ์ธํ๋ ๋ฐ ์ค์ํฉ๋๋ค.
E2E ํ ์คํธ ํ๋ ์์ํฌ ์ ํ
TypeScript์์ ์ฌ์ฉํ ์ ์๋ ๋ช ๊ฐ์ง ์ธ๊ธฐ ์๋ E2E ํ ์คํธ ํ๋ ์์ํฌ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- Cypress: ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ์ ์ฌ์ฉ์ ์ํธ ์์ฉ์ ์๋ฎฌ๋ ์ด์ ํ๋ ํ ์คํธ๋ฅผ ์์ฑํ ์ ์๋ ๊ฐ๋ ฅํ๊ณ ์ฌ์ฉ์ ์นํ์ ์ธ E2E ํ ์คํ ํ๋ ์์ํฌ์ ๋๋ค.
- Playwright: TypeScript๋ฅผ ํฌํจํ ์ฌ๋ฌ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ฅผ ์ง์ํ๋ ํฌ๋ก์ค ๋ธ๋ผ์ฐ์ ํ ์คํ ํ๋ ์์ํฌ์ ๋๋ค.
- Puppeteer: ํค๋๋ฆฌ์ค Chrome ๋๋ Chromium์ ์ ์ดํ๊ธฐ ์ํ ๊ณ ๊ธ API๋ฅผ ์ ๊ณตํ๋ Node ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.
Cypress๋ ์ฌ์ฉ ํธ์์ฑ๊ณผ ํฌ๊ด์ ์ธ ๊ธฐ๋ฅ์ผ๋ก ์ธํด ์น ์ ํ๋ฆฌ์ผ์ด์ ์ E2E ํ ์คํธ์ ํนํ ์ ํฉํฉ๋๋ค. Playwright๋ ํฌ๋ก์ค ๋ธ๋ผ์ฐ์ ํธํ์ฑ ๋ฐ ๊ณ ๊ธ ๊ธฐ๋ฅ์ ํ์ํฉ๋๋ค. Cypress๋ฅผ ์ฌ์ฉํ์ฌ E2E ํ ์คํธ ๊ฐ๋ ์ ์์ฐํ ๊ฒ์ ๋๋ค.
์์: Cypress๋ฅผ ์ฌ์ฉํ E2E ํ ์คํธ
๋ก๊ทธ์ธ ์์์ด ์๋ ๊ฐ๋จํ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ณ ๋ คํด ๋ณด์ธ์. ์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ํ E2E ํ ์คํธ๋ ๋ค์์ ํฌํจํ ์ ์์ต๋๋ค:
- ๋ก๊ทธ์ธ ํ์ด์ง ๋ฐฉ๋ฌธ.
- ์ ํจํ ์๊ฒฉ ์ฆ๋ช ์ ๋ ฅ.
- ์์ ์ ์ถ.
- ์ฌ์ฉ์๊ฐ ํ ํ์ด์ง๋ก ๋ฆฌ๋๋ ์ ๋์๋์ง ํ์ธ.
// cypress/integration/login.spec.ts
describe('Login', () => {
it('should log in successfully with valid credentials', () => {
cy.visit('/login');
cy.get('#username').type('valid_user');
cy.get('#password').type('valid_password');
cy.get('button[type="submit"]').click();
cy.url().should('include', '/home');
cy.contains('Welcome, valid_user').should('be.visible');
});
it('should display an error message with invalid credentials', () => {
cy.visit('/login');
cy.get('#username').type('invalid_user');
cy.get('#password').type('invalid_password');
cy.get('button[type="submit"]').click();
cy.contains('Invalid username or password').should('be.visible');
});
});
์ด ์์๋ Cypress๋ฅผ ์ฌ์ฉํ์ฌ ์น ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ์ ์ฌ์ฉ์ ์ํธ ์์ฉ์ ์๋ฎฌ๋ ์ด์ ํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์๋๋ก ๋์ํ๋์ง ํ์ธํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค. Cypress๋ DOM๊ณผ ์ํธ ์์ฉํ๊ณ , ๋จ์ธ(assertion)์ ์ํํ๋ฉฐ, ์ฌ์ฉ์ ์ด๋ฒคํธ๋ฅผ ์๋ฎฌ๋ ์ด์ ํ๊ธฐ ์ํ ๊ฐ๋ ฅํ API๋ฅผ ์ ๊ณตํฉ๋๋ค.
Cypress ํ ์คํธ์ ํ์ ์์ ์ฑ
Cypress๋ ์ฃผ๋ก JavaScript ๊ธฐ๋ฐ ํ๋ ์์ํฌ์ด์ง๋ง, TypeScript๋ฅผ ํ์ฉํ์ฌ E2E ํ ์คํธ์ ํ์ ์์ ์ฑ์ ํฅ์์ํฌ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, TypeScript๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์ ์ ์ ๋ช ๋ น์ ์ ์ํ๊ณ API ํธ์ถ์ ์ํด ๋ฐํ๋๋ ๋ฐ์ดํฐ์ ํ์ ์ ์ง์ ํ ์ ์์ต๋๋ค.
TypeScript ํ ์คํ ์ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
TypeScript ํ ์คํธ๊ฐ ํจ๊ณผ์ ์ด๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ๋๋ก ๋ณด์ฅํ๋ ค๋ฉด ๋ค์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๊ณ ๋ คํ์ญ์์ค:
- ์ผ์ฐ ๊ทธ๋ฆฌ๊ณ ์์ฃผ ํ ์คํธ ์์ฑ: ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ ์ด๋ฐ๋ถํฐ ํ ์คํธ๋ฅผ ํตํฉํ์ญ์์ค. ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ(TDD)์ ํ๋ฅญํ ์ ๊ทผ ๋ฐฉ์์ ๋๋ค.
- ํ ์คํธ ์ฉ์ด์ฑ์ ์ง์ค: ์ฝ๋๋ฅผ ์ฝ๊ฒ ํ ์คํธํ ์ ์๋๋ก ์ค๊ณํ์ญ์์ค. ์ข ์์ฑ ์ฃผ์ ์ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฆฌํ๊ณ ๋ชจ์(mock)ํ๊ธฐ ์ฝ๊ฒ ๋ง๋์ญ์์ค.
- ํ ์คํธ๋ฅผ ์๊ณ ์ง์ค์ ์ผ๋ก ์ ์ง: ๊ฐ ํ ์คํธ๋ ์ฝ๋์ ๋จ์ผ ์ธก๋ฉด์ ์ง์คํด์ผ ํฉ๋๋ค. ์ด๋ ํ ์คํธ๋ฅผ ์ดํดํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
- ์ค๋ช ์ ์ธ ํ ์คํธ ์ด๋ฆ ์ฌ์ฉ: ํ ์คํธ๊ฐ ๋ฌด์์ ๊ฒ์ฆํ๋์ง ๋ช ํํ๊ฒ ์ค๋ช ํ๋ ํ ์คํธ ์ด๋ฆ์ ์ ํํ์ญ์์ค.
- ๋์ ์์ค์ ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง ์ ์ง: ์ฝ๋์ ๋ชจ๋ ๋ถ๋ถ์ด ์ ์ ํ ํ ์คํธ๋๋๋ก ๋์ ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ๋ชฉํ๋ก ํ์ญ์์ค.
- ํ ์คํธ ์๋ํ: ์ฝ๋ ๋ณ๊ฒฝ์ด ์์ ๋๋ง๋ค ํ ์คํธ๊ฐ ์๋์ผ๋ก ์คํ๋๋๋ก ์ง์์ ํตํฉ(CI) ํ์ดํ๋ผ์ธ์ ํ ์คํธ๋ฅผ ํตํฉํ์ญ์์ค.
- ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง ๋๊ตฌ ์ฌ์ฉ: ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ์ธก์ ํ๊ณ ์ ์ ํ ํ ์คํธ๋์ง ์์ ์ฝ๋ ์์ญ์ ์๋ณํ๋ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ญ์์ค.
- ํ ์คํธ ์ ๊ธฐ์ ์ผ๋ก ๋ฆฌํฉํ ๋ง: ์ฝ๋๊ฐ ๋ณ๊ฒฝ๋จ์ ๋ฐ๋ผ ํ ์คํธ๋ฅผ ๋ฆฌํฉํ ๋งํ์ฌ ์ต์ ์ํ๋ฅผ ์ ์งํ๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ๋๋ก ํ์ญ์์ค.
- ํ ์คํธ ๋ฌธ์ํ: ํ ์คํธ์ ๋ชฉ์ ๊ณผ ๊ฐ์ ํ๋ ๋ฐ๋ฅผ ์ค๋ช ํ๊ธฐ ์ํด ํ ์คํธ์ ์ฃผ์์ ์ถ๊ฐํ์ญ์์ค.
- AAA ํจํด ๋ฐ๋ฅด๊ธฐ: Arrange(์ค๋น), Act(์คํ), Assert(๋จ์ธ). ์ด๋ ํ ์คํธ์ ๊ฐ๋ ์ฑ์ ์ํ ๊ตฌ์กฐํ์ ๋์์ด ๋ฉ๋๋ค.
๊ฒฐ๋ก : ํ์ ์์ ์ฑ TypeScript ํ ์คํ ์ผ๋ก ๊ฒฌ๊ณ ํ ์ ํ๋ฆฌ์ผ์ด์ ๊ตฌ์ถ
TypeScript์ ๊ฐ๋ ฅํ ํ์ดํ ์์คํ ์ ๊ฒฌ๊ณ ํ๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๊ธฐ ์ํ ๊ฐ๋ ฅํ ๊ธฐ๋ฐ์ ์ ๊ณตํฉ๋๋ค. ํ ์คํ ์ ๋ต์์ ํ์ ์์ ์ฑ์ ํ์ฉํจ์ผ๋ก์จ, ์ค๋ฅ๋ฅผ ์กฐ๊ธฐ์ ๊ฐ์งํ๊ณ ์ฝ๋์ ์ ๋ฐ์ ์ธ ํ์ง์ ํฅ์์ํค๋ ๋ ์ ๋ขฐํ ์ ์๊ณ ํจ๊ณผ์ ์ธ ํ ์คํธ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ์ด ๊ธ์ ๋จ์ ํ ์คํธ๋ถํฐ ํตํฉ ํ ์คํธ, ์ข ๋จ ๊ฐ ํ ์คํธ์ ์ด๋ฅด๊ธฐ๊น์ง ๋ค์ํ TypeScript ํ ์คํ ์ ๋ต์ ํ๊ตฌํ๋ฉฐ, TypeScript ํ ์คํ ์ ๋ํ ํฌ๊ด์ ์ธ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํ์ต๋๋ค. ์ด ๊ธ์ ์ ์๋ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฆ์ผ๋ก์จ, TypeScript ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ฒ ์ ํ ํ ์คํธ๋๊ณ ํ๋ก๋์ ์ ๋๋น๋ ์ ์๋๋ก ๋ณด์ฅํ ์ ์์ต๋๋ค. ์ฒ์๋ถํฐ ํฌ๊ด์ ์ธ ํ ์คํ ์ ๊ทผ ๋ฐฉ์์ ์์ฉํ๋ฉด ์ ์ธ๊ณ ๊ฐ๋ฐ์๋ค์ด ๋ ์ ๋ขฐํ ์ ์๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์ํํธ์จ์ด๋ฅผ ์์ฑํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํค๊ณ ๊ฐ๋ฐ ๋น์ฉ์ ์ ๊ฐํ ์ ์์ต๋๋ค. TypeScript ์ฑํ์ด ๊ณ์ ์ฆ๊ฐํจ์ ๋ฐ๋ผ, ํ์ ์์ ์ฑ ํ ์คํ ์ ๋ง์คํฐํ๋ ๊ฒ์ ์ ์ธ๊ณ ์ํํธ์จ์ด ์์ง๋์ด์๊ฒ ์ ์ ๋ ๊ฐ์น ์๋ ๊ธฐ์ ์ด ๋๊ณ ์์ต๋๋ค.